﻿/*
 *  Author: Louis A. Leskoviansky
 *  Company: Artemis Solutions Group (http://www.artemis-solutions.com)
 */


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.SessionState;
using System.Web.UI;

namespace AjaxControlFramework
{
    public class DiskStateStrategy : StateStrategy
    {
        //------// Properties \\--------------------------------------------\\
        private string _stateCachePath = null;
        public virtual string StateCachePath
        {
            get
            {
                if (_stateCachePath == null)
                {
                    _stateCachePath = base.Page.MapPath("~/App_Data/AJAX Control State/");
                }

                return _stateCachePath;
            }
        }
        //------\\ Properties //--------------------------------------------//



        //------// Constructors \\------------------------------------------\\
        public DiskStateStrategy(Control targetControl)
            : base(targetControl)
        { }
        //------\\ Constructors //------------------------------------------//



        //------// Methods \\-----------------------------------------------\\
        protected override void PersistState()
        {
            if (base.ViewState != null || base.ControlState != null)
            {
                // Serialize both the page ControlState and ViewState.
                string controlState = base.StateFormatter.Serialize(new Pair(base.ViewState, base.ControlState));

                string stateFileName = GetStateFileName();

                if (!Directory.Exists(StateCachePath))
                {
                    Directory.CreateDirectory(StateCachePath);
                }


                bool saveFileNameToCache = false;

                if (!File.Exists(StateCachePath + stateFileName))
                {
                    saveFileNameToCache = true;
                }

                File.WriteAllText(StateCachePath + stateFileName, controlState);


                // Save the file name to the cache and provide and anonymous handler to delete the file once the 
                // cache value has expired.
                if (saveFileNameToCache)
                {
                    HttpContext.Current.Cache.Add(stateFileName, (byte)1, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, HttpContext.Current.Session.Timeout, 0), CacheItemPriority.High, delegate(string key, object value, CacheItemRemovedReason reason)
                    {
                        if (File.Exists(StateCachePath + key))
                        {
                            File.Delete(StateCachePath + key);
                        }
                    });
                }
            }
        }


        protected override void RestoreState()
        {
            string stateFileName = GetStateFileName();
            string stateFullPath = StateCachePath + stateFileName;

            string controlState = null;

            if (File.Exists(stateFullPath))
            {
                controlState = File.ReadAllText(StateCachePath + stateFileName);

                if (controlState != null && controlState != String.Empty)
                {
                    Pair statePair = (Pair)base.StateFormatter.Deserialize(controlState);

                    base.ViewState = statePair.First;
                    base.ControlState = statePair.Second;
                }
            }
            else
            {
                ViewState = null;
                ControlState = null;
            }
        }


        protected virtual string GetStateFileName()
        {
            return new SessionIDManager().GetSessionID(HttpContext.Current) + "_" + TargetControl.UniqueID + "_" + HttpUtility.UrlEncode(TargetControl.Page.Request.Url.PathAndQuery) + ".state";
        }
        //------\\ Methods //-----------------------------------------------//
    }
}
